package com.wavefull.core.util

import android.os.Handler
import android.os.Looper

object TaskManager {
    private val handler by lazy { Handler(Looper.getMainLooper()) }
    private val tasks by lazy { mutableMapOf<String, Runnable>() }

    /**
     * 开启定时
     */
    @JvmOverloads
    fun startTask(
        taskName: String? = null,
        delayMillis: Long,
        periodMillis: Long = -1,
        taskType: Int = TaskType.ONCE,
        clz: Class<out Any>? = null,
        task: () -> Unit
    ) {
        if (taskName == null && clz == null) {
            throw Throwable(message = "taskName和clz不能同时为空")
        }
        val actualTaskName = taskName ?: getCallerMethodName(clz!!)
        val runnable = object : Runnable {
            override fun run() {
                stopTask(actualTaskName)
                task()
                if (taskType == TaskType.REPEATED && periodMillis >= 0) {
                    handler.postDelayed(this, periodMillis)
                }
            }
        }
        tasks[actualTaskName] = runnable
        if (taskType == TaskType.REPEATED && periodMillis >= 0) {
            handler.postDelayed(runnable, delayMillis)
        } else {
            handler.postDelayed(runnable, delayMillis)
        }
    }

    /**
     * 关闭定时器
     */
    fun stopTask(taskName: String) {
        tasks[taskName]?.let {
            handler.removeCallbacks(it)
            tasks.remove(taskName)
        }
    }

    /**
     * 清除所有定时任务
     */
    fun stopAllTasks() {
        tasks.values.forEach {
            handler.removeCallbacks(it)
        }
        handler.removeCallbacksAndMessages(null)
        tasks.clear()
    }

    private fun getCallerMethodName(clz: Class<out Any>): String {
        val stackTrace = Thread.currentThread().stackTrace
        var callerMethodName = ""
        for (i in 2 until stackTrace.size) {
            val declaringClass = stackTrace[i].className
            if (declaringClass == clz.name) {
                val methodName = stackTrace[i].methodName
                callerMethodName = methodName
                break
            }
        }
        return callerMethodName
    }
}

object TaskType {
    const val ONCE = 0
    const val REPEATED = 1
}
